package com.free4inno.knowledgems.controller;

import com.free4inno.knowledgems.constants.ResourceConstants;
import com.free4inno.knowledgems.constants.UserConstants;
import com.free4inno.knowledgems.dao.*;
import com.free4inno.knowledgems.domain.*;
import com.free4inno.knowledgems.service.FileService;
import com.free4inno.knowledgems.utils.LogUtils;
import com.free4inno.knowledgems.service.ResourceEsService;
import com.free4inno.knowledgems.service.ResourceService;
import com.free4inno.knowledgems.utils.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.*;

import static com.free4inno.knowledgems.utils.CompleteUriUtils.getCompleteUri;

/**
 * Author HUYUZHU.
 * Date 2020/9/25 13:12.
 */

@Slf4j
@Controller
@RequestMapping("/resource")
public class ResourceController {


    @Autowired
    private ResourceDAO resourceDao;

    @Autowired
    private AttachmentDAO attachmentDao;

    @Autowired
    private UserDAO userDao;

    @Autowired
    private CommentDAO commentDao;

    @Autowired
    private ResourceService resourceService;

    @Autowired
    private SpecResourceDAO specResourceDao;

    @Autowired
    private ResourceEsService esService;

    @Autowired
    private SystemManageDAO systemManageDao;

    @Autowired
    private LabelInfoDAO labelInfoDao;

    @Autowired
    private ImageUtils imageUtils;

    @Autowired
    private FileService fileService;

    @Autowired
    private WriteEsResourceHttpUtils writeEsResourceHttpUtils;

    @RequestMapping("/resource")
    public String resource(@RequestParam(value = "id", required = true) int id,
                           @RequestParam(value = "isBook", required = false) boolean isBook,
                           HttpSession session, HttpServletRequest request, HttpServletResponse httpServletResponse, Map param) {
        log.info(LogUtils.parse(ResourceConstants.OPEN_RESOURCE, "资源id: " + id));

        Resource resource = resourceDao.findAllById(id);
//        System.out.println("-----"+resource.getText());
        //取用户名
        User user = new User();
        user.setRealName(UserConstants.USERNAME);
        user = userDao.findById(resource.getUserId()).orElse(user);
        //取群组名
        resource.setGroupName(resourceService.getGroupName(resource));
        //取标签名
        resource.setLabelName(resourceService.getLabelName(resource));
        //取资源的推荐情况
        resourceService.setRecommendResource(resource);
        //取资源的公告情况
        resourceService.setAnnouncementResource(resource);
        // （此处的保存是为了保存未同步的资源推荐与公告情况）
        resourceDao.save(resource);

        // get book label id
        String bookLabelId = systemManageDao.findAllByVariable("book_label").get().getValue();
        LabelInfo labelInfo = labelInfoDao.findAllById(Integer.parseInt(bookLabelId));
        String bookLabelName = ResourceConstants.DEFAULT_NAME;
        if (labelInfo != null) {
            bookLabelName = labelInfo.getLabelName();
        }

        //取资源的附件
        String attachment = resourceService.getAttachmentJson(id);
        param.put(ResourceConstants.ATTACHMENT, attachment);
        //获取这个资源的uri
        String completeUri = getCompleteUri(request);
        session.setAttribute(UserConstants.COMPLETE_URI, completeUri);
        //判断是否为公开资源
        Boolean isPublic;
        Boolean isInGroup;
        if (resource.getPermissionId() == 0) {
            /* 非公开资源 */
            isPublic = false;
            log.info(LogUtils.parse(ResourceConstants.OPEN_RESOURCE, ResourceConstants.NOTPULIC_RESOURCE));
            // 判断是否登录
            if (session.getAttribute(UserConstants.ACCOUNT) == null) {
                log.warn(LogUtils.parse(ResourceConstants.OPEN_RESOURCE, ResourceConstants.NOTPULIC_NOTLOGIN));
                try {
                    httpServletResponse.sendRedirect("/login");
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return "/login/login";
            } else {
                // 判断用户是否在资源群组内
                isInGroup = resourceService.isInResourceGroup(resource, (int) session.getAttribute(UserConstants.USER_ID));
            }
        } else {
            /* 公开资源 */
            isPublic = true;
            isInGroup = true;
            log.info(LogUtils.parse(ResourceConstants.OPEN_RESOURCE, "当前资源为公开资源"));
        }

        param.put(ResourceConstants.RESOURCE, resource);
        param.put(ResourceConstants.USER, user);
        param.put(ResourceConstants.BOOK_LABEL_NAME, bookLabelName);
        param.put("user_id", user.getId());

        //判断用户是否有权限打开
        if (!isPublic && !isInGroup) {
            log.warn(LogUtils.parse(ResourceConstants.OPEN_RESOURCE, "当前资源为非公开资源，且用户不在群组内，跳转reject页面"));
            return "/resource/rejectResource";
        }
        //判断是否书籍
        if (isBook) {
            log.info(LogUtils.parse(ResourceConstants.OPEN_RESOURCE, "打开书籍资源，转到页面"));
            return "/resource/bookResource";
        }
        log.info(LogUtils.parse(ResourceConstants.OPEN_RESOURCE, "打开普通资源，转到页面"));
        return "/resource/resource";
    }

    @ResponseBody
    @PostMapping("/changePermission")
    public String changePermission(@RequestParam("id") int id, HttpSession session) {
        log.info(LogUtils.parse(ResourceConstants.MODIFY_RESOURCE_PERMISSION, "资源id: " + id));

        String result = "";
        Resource resource = resourceDao.findResourceById(id);
        //反转resource.permissionId的值
        if (resource.getPermissionId() == 0) {
            resource.setPermissionId(1);
            result = "permissionId=1";
        } else {
            resource.setPermissionId(0);
            result = "permissionId=0";
        }
        resourceDao.save(resource);
        esService.updateResourceES(id);

        log.info(LogUtils.parse(ResourceConstants.MODIFY_RESOURCE_PERMISSION, "返回反转后的当前资源权限类型, " + result));
        return result;
    }

    @RequestMapping("/deleteResource")
    public String deleteResource(@RequestParam("id") int id, HttpSession session) {
        log.info(LogUtils.parse(ResourceConstants.DELETE_RESOURCE, "资源id: " + id));
        //删除正文中图片
        Resource resource = resourceDao.findResourceById(id);
        String text = resource.getText();
        List<String> imageSrc = imageUtils.getImgSrc(text);
        String result = "";
        for (String src : imageSrc) {
            result = imageUtils.deleteImage(src);
        }
        //删除resource表里的一条数据
        resourceDao.deleteById(id);
        //删除ES索引中的一条数据
        esService.deleteResourceES(id);
        //删除spec表里的一条数据
        if (specResourceDao.findByResourceId(id) != null) {
            specResourceDao.deleteByResourceId(id);
        }
        //删除评论
        if (commentDao.findByResourceId(id) != null && commentDao.findByResourceId(id).size() != 0) {
            commentDao.deleteAllByResourceId(id);
        }
        // 删除附件
        List<Attachment> attachmentList = attachmentDao.findAllByResourceId(id);
        if (attachmentList != null && attachmentList.size() != 0) {
            for (Attachment attachemnt : attachmentList) {
                String url = attachemnt.getUrl();
                log.info(this.getClass().getName() + "----out----" + "删除附件" + "----" + url);
                if (fileService.deleteFile(url)) {
                    log.info(this.getClass().getName() + "删除附件成功" + "----" + url);
                } else {
                    log.info(this.getClass().getName() + "删除附件错误" + "----" + url);
                }
            }
        }
        log.info(LogUtils.parse(ResourceConstants.DELETE_RESOURCE, "删除成功"));
        return "redirect:/";
    }

    @RequestMapping("/getComment")
    public String getComment(@RequestParam("resourceId") int resourceId,
                             @RequestParam("page") int page,
                             Map param, HttpSession session) {
        log.info(LogUtils.parse(ResourceConstants.GET_COMMENT, "resourceId: " + resourceId + ", page: " + page));
        int pageSize = 5;
        Sort sort = Sort.by(Sort.Direction.DESC, "time");
        Pageable pageable = PageRequest.of(page, pageSize, sort);
        Page<Comment> commentPage = commentDao.findAllByResourceId(resourceId, pageable);
        List<Comment> commentList = commentPage.getContent();
        int pageTotal = commentPage.getTotalPages();
        long commentTotal = commentPage.getTotalElements();
        for (Comment comment : commentList) {
            String userName = userDao.findById(comment.getUserId()).get().getRealName();
            comment.setUserName(userName);
            int picID = (int) userName.charAt(1) % 20;
            String picName = picID + ".png";
            comment.setPicName(picName);
        }

        /*
        List<Comment> sortedList = new ArrayList<>(commentList);
        Collections.sort(sortedList, new Comparator<Comment>() {
            @Override
            public int compare(Comment c1, Comment c2) {
                long t1 = c1.getTime().getTime();
                long t2 = c2.getTime().getTime();
                if(t1 < t2) return 1;
                else if(t1 == t2) return 0;
                else return -1;
            }
        });
        if (sortedList.size() >= 2) {
            Comment lastComment = sortedList.remove(sortedList.size() - 1); // 移除最后一个元素
            sortedList.add(0, lastComment); // 将最后一个元素添加到第一个位置
        }
         */
        param.put(ResourceConstants.COMMENT_LIST, commentList);
        //param.put(ResourceConstants.COMMENT_LIST, sortedList);
        param.put(ResourceConstants.PAGE_TOTAL, pageTotal);
        param.put(ResourceConstants.COMMENT_TOTAL, commentTotal);
        param.put(ResourceConstants.RESOURCE_ID, resourceId);
        if (session.getAttribute(UserConstants.USER_ID) == null) {
            param.put(ResourceConstants.USER_ID, "");
            param.put(ResourceConstants.USER_NAME, "");
            session.setAttribute("login_flag", 0);
        } else {
            param.put(ResourceConstants.USER_ID, session.getAttribute(UserConstants.USER_ID));
            param.put(ResourceConstants.USER_NAME, userDao.findById((int) session.getAttribute(UserConstants.USER_ID)).get().getRealName());
        }
        log.info(LogUtils.parse(ResourceConstants.GET_COMMENT, "返回_comment子页"));
        return "resource/_comment";
    }

    class MyStruct {
        int id;
        int resourceId;
        int userId;
        String content;
        Timestamp time;
        String userName;
        String picName;
    }

    @ResponseBody
    @RequestMapping("/newComment")
    public Comment newComment(@RequestParam("content") String content,
                             @RequestParam("resourceId") int resourceId, HttpSession session, HttpServletRequest request) throws Exception {
        log.info(LogUtils.parse(ResourceConstants.ADD_COMMENT, "resourceId: " + resourceId));

        Comment comment = new Comment();
        try {
            String contentHtml = "<p class=\"mb-0\">" + StringUtils.inputStringFormat(content).replaceAll("<br/>", "</p><p class=\"mb-0\">") + "</p>";
            contentHtml = imageUtils.DownloadExternalImage(contentHtml, session); //调用ImageUtils下载外链图片的方法

            comment.setUserId((int) session.getAttribute(UserConstants.USER_ID));
            comment.setTime(new Timestamp(new Date().getTime()));
            comment.setContent(contentHtml);
            comment.setResourceId(resourceId);

            commentDao.save(comment);

            // 暂时不考虑这个出错
            Resource resource = resourceDao.findResourceById(resourceId);
            ResourceES resourceES = new ResourceES();
            new Thread(new Runnable() {
                @SneakyThrows
                @Override
                public void run() {
                    writeEsResourceHttpUtils.writeResourceToESHTTP(resource, resourceES);
                }
            }).start();
            log.info(LogUtils.parse(ResourceConstants.ADD_COMMENT, "评论添加成功"));

            // 添加需要的信息
            String userName = userDao.findById(comment.getUserId()).get().getRealName();
            comment.setUserName(userName);
            int picID = (int) userName.charAt(1) % 20;
            String picName = picID + ".png";
            comment.setPicName(picName);
        } catch (Exception e) {
            log.info(LogUtils.parse(ResourceConstants.ADD_COMMENT, "评论添加失败"));
            comment.setId(-1);
        }
        return comment;

        /*
        MyStruct myStruct = new MyStruct();
        myStruct.id = comment.getId();
        myStruct.resourceId = comment.getResourceId();
        myStruct.userId = comment.getUserId();
        myStruct.content = comment.getContent();
        myStruct.time = comment.getTime();
        myStruct.userName = comment.getUserName();
        myStruct.picName = comment.getPicName();
        return myStruct;

         */
    }

    @ResponseBody
    @RequestMapping("/deleteComment")
    public String deleteComment(@RequestParam("commentId") int commentId, HttpSession session) {
        log.info(LogUtils.parse(ResourceConstants.DELETE_COMMENT, "评论Id: " + commentId));
        String result;
        try {
            commentDao.deleteById(commentId);
            log.info(LogUtils.parse(ResourceConstants.DELETE_COMMENT, "删除成功"));
            result = "ok";
        } catch (Exception e) {
            log.info(LogUtils.parse(ResourceConstants.DELETE_COMMENT, "删除失败"));
            result = "fail";
        }
        return result;
    }

    @ResponseBody
    @RequestMapping("/updateComment")
    public String editComment(@RequestParam("commentId") int commentId, @RequestParam("commentInfo") String commentInfo, HttpSession session) {
        String result = "fail";
        log.info(LogUtils.parse(ResourceConstants.UPDATE_COMMENT, "评论Id: " + commentId));

        Optional<Comment> optionalComment = commentDao.findById(commentId);
        if (optionalComment.isPresent()) {
            Comment comment = optionalComment.get();
            comment.setContent(commentInfo);
            commentDao.save(comment);
            log.info(LogUtils.parse(ResourceConstants.DELETE_COMMENT, "编辑成功：" + commentInfo));
            result = "ok";
        } else {
            // Optional 中没有 Comment 对象，处理空值的情况
            log.info(LogUtils.parse(ResourceConstants.DELETE_COMMENT, "编辑失败：" + commentInfo));
        }

        return result;
    }
}
